<?php
namespace app\wechat\controller;

use think\Controller;

class Index extends Controller{

  public function index(){
    if(!isset($_GET['echostr'])){
      $this->responseMsg();
    }else{
      $this->valid();
    }
  }

  /**
   * [微信公众平台 服务器配置]
   * 接入微信公众平台API 验证签名
   * @return []
   */
  public function valid(){
    # 1.将timestamp,nonce,token 按字典序排序
    $timestamp = $_GET['timestamp']; // 时间戳
    $nonce     = $_GET['nonce']; // 随机字符串
    $token     = config('wechat_token'); // 自定义的令牌
    $signature = $_GET['signature']; // 在微信公众平台已经加密好的字符串
    $echoStr   = $_GET['echostr'];
    // sort() 函数对数值数组进行升序排序。
    $tmpArr = [$timestamp,$nonce,$token];
    sort($tmpArr); // 按自然排序

    # 2.将排序后的三个参数拼接之后用sha1加密
    // tmp 递归简写 临时 str 简写 字符串
    // implode() 函数返回一个由数组元素组合成的字符串
    // 或者使用 join()  implode()函数的别名
    $tmpStr = implode('',$tmpArr);
    $tmpStr = sha1($tmpStr); // 用哈希加密法加密

    # 3.将加密后的字符串与signature进行对比，判断该请求是否来自微信
    if($tmpStr == $signature){
      // 第一次接入weixin api接口的时候 才会验证合法性
      // 第一次是特殊 ，多传了一个参数$echostr
      echo $echoStr; // 输出微信传过来的GET['echostr']
      exit;
    }
  }

  /**
   * [接收事件推送并回复/响应]
   * @return [type] [description]
   */
  public function responseMsg(){
    # 1.获取到微信推送过来post数据 (xml格式)
    // $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
    $postArr = file_get_contents("php://input");
    // $tmpStr = $postArr;
    # 2.处理消息类型，并设置回复类型和内容
    /*
    <xml>
      <ToUserName>< ![CDATA[toUser] ]></ToUserName>
      <FromUserName>< ![CDATA[fromUser] ]></FromUserName>
      <CreateTime>1348831860</CreateTime>
      <MsgType>< ![CDATA[text] ]></MsgType>
      <Event>< ![CDATA[subscribe] ]></Event>
    </xml>
    */
    // simplexml_load_string() 函数转换形式良好的 XML 字符串为 SimpleXMLElement 对象。
    $postObj = simplexml_load_string($postArr);
    // $postObj->ToUserName = '';
    // $postObj->FromUserName = '';
    // $postObj->CreateTime = '';
    // $postObj->MsgType = '';
    // $postObj->Event = '';

    # 获取接受到的数据类型
    // trim()过滤左右两边空格 strtolower()转为小写
    $RX_TYPE = trim(strtolower($postObj->MsgType));

    # subscribe 关注 unsubscribe 取消关注
    if( ($RX_TYPE == 'event') && ($postObj->Event == "subscribe" || $postObj->Event == "unsubscribe" || $postObj->Event == "TEMPLATESENDJOBFINISH") ){
      // 过滤关注和取消关注事件
    }else{
      //更新互动记录
    }

    # 消息类型分离
    switch($RX_TYPE){
      case 'event':
        $result = $this->receiveEvent($postObj);
        break;
      case 'text':
        $result = $this->receiveText($postObj);
        break;
      default:
        $result = 'unknown msg type：' . $RX_TYPE;
    }
    echo $result;
  }

  /**
   * 接受事件消息
   * @param  [type] $postObj [description]
   * @return [type]          [description]
   */
  private function receiveEvent($postObj){
    // strval()获取变量数值且转为字符串类型
    // $openid  = strval($postObj->FromUserName);
    // $content = '';

    switch($postObj->Event){
      case 'subscribe':
        // $content  = '欢迎关注DXing1202的微信公众账号';
        $content = '公众账号：' . $postObj->ToUserName
                    . "\n微信用户的openid：" . $postObj->FromUserName;
        break;
      default:
        $content = '';
    }
    if(is_array($content)){
      $result = $this->transmitNews($postObj,$content);
    }else{
      $result = $this->transmitText($postObj,$content);
    }
    return $result;
  }

  /**
   * 接收文本消息 根据文字回复内容
   * @param  [type] $postObj [description]
   * @return [type]          [description]
   */
  private function receiveText($postObj){
    // 这里加上trim() 防止客户的输入带有空格而无法匹配
    $keyword = trim($postObj->Content);
    // 获取客户openid
    $openid  = strval($postObj->FromUserName);

    switch($keyword){
      case 1:
        $content = '您输入的数字是1';
      break;
      case 2:
        $content = '您输入的数字是2';
      break;
      case 3:
        $content = '您输入的数字是3';
      break;
      case 4:
        // 在回复的纯文本消息中设置链接
        $content = "<a href='http://www.imooc.com'>慕课网</a>";
      break;
      case '英文':
        $content = 'englist is ok';
      break;
      case 'imooc':
        $content = 'imooc is very good';
      break;
      case 'tuwen':
        // 单图文演示
        $content = [
          [
            'title'       => 'imooc',
            'description' => 'imooc is very cool',
            'picUrl'      => 'https://www.imooc.com/static/img/index/logo.png',
            'url'         => 'http://www.imooc.com'
          ]
        ];
        break;
      case 'tuwen2':
        // 多图文演示
        $content = [
          [
            'title'       => 'hao123',
            'description' => 'hao123 is very cool',
            'picUrl'      => 'https://gss0.bdstatic.com/5bVWsj_p_tVS5dKfpU_Y_D3/res/r/image/2017-09-27/297f5edb1e984613083a2d3cc0c5bb36.png',
            'url'         => 'http://www.hao123.com'
          ],
          [
            'title'       => 'xiaomi',
            'description' => 'xiaomi is very cool',
            'picUrl'      => 'https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=109099697,1738114976&fm=58&s=A5D7CB36FF48CE1140F385FE0300D03B&bpow=121&bpoh=75',
            'url'         => 'http://www.xiaomi.com'
          ],
          [
            'title'       => 'imooc',
            'description' => 'imooc is very cool',
            'picUrl'      => 'https://www.imooc.com/static/img/index/logo.png',
            'url'         => 'http://www.imooc.com'
          ]
        ];
        break;
      default:
        $content = '对不起，暂时未提供该关键字的回复内容。' .
                    "\nSorry,No reply to the keyword has been provided." .
                    "\n" . date("Y-m-d H:i:s",time()) .
                    "\n感谢 " . $openid . "\n技术支持 DXing1202";
    }

    if(is_array($content)){
      $result = $this->transmitNews($postObj,$content);
    }else{
      $result = $this->transmitText($postObj,$content);
    }
    return $result;
  }

  /**
   * 回复文本消息 纯文本回复代码实现
   * @param  [type] $postObj [description]
   * @param  [type] $content [description]
   * @return [type]          [description]
   */
  private function transmitText($postObj,$content){
    if(!isset($content) || empty($content)){
      return '';
    }
    $xmlTpl = "<xml>
                  <ToUserName><![CDATA[%s]]></ToUserName>
                  <FromUserName><![CDATA[%s]]></FromUserName>
                  <CreateTime>%s</CreateTime>
                  <MsgType><![CDATA[%s]]></MsgType>
                  <Content><![CDATA[%s]]></Content>
                </xml>";
    $result = sprintf($xmlTpl,$postObj->FromUserName,$postObj->ToUserName,time(),'text',$content);
    return $result;
  }

  /**
   * 回复图文消息 图文回复代码实现
   * @param  [type] $postObj [description]
   * @param  [type] $newsArr [description]
   * @return [type]          [description]
   */
  private function transmitNews($postObj,$newsArr){
    if(!is_array($newsArr)){
      return '';
    }
    # 图文消息个数，限制为10条以内。如果图文超过10则将会无响应
    # 多条图文消息信息，默认第一个item为大图
    # picUrl 支持JPG、PNG格式，较好的效果为大图360*200 小图200*200
    $itemTpl = "<item>
                <Title><![CDATA[%s]]></Title>
                <Description><![CDATA[%s]]></Description>
                <PicUrl><![CDATA[%s]]></PicUrl>
                <Url><![CDATA[%s]]></Url>
               </item>";
    $item_str = '';
    foreach($newsArr as $item){
      $item_str .= sprintf($itemTpl, $item['title'], $item['description'], $item['picUrl'], $item['url']);
    }
    $xmlTpl = "<xml>
                <ToUserName><![CDATA[%s]]></ToUserName>
                <FromUserName><![CDATA[%s]]></FromUserName>
                <CreateTime>%s</CreateTime>
                <MsgType><![CDATA[%s]]></MsgType>
                <ArticleCount>%s</ArticleCount>
                <Articles>{$item_str}</Articles>
               </xml>";
    $result = sprintf($xmlTpl,$postObj->FromUserName,$postObj->ToUserName,time(),'news',count($newsArr));
    return $result;
  }


}
